package de.dailab.graphworld.pathfinding;

import java.util.ArrayList;

import de.dailab.graphworld.ontology.Edge;
import de.dailab.graphworld.ontology.Node;

// unility class for paths in the graph to be used by A*
public class Path implements Comparable<Path>{
	
	// path contains of a start node, edges, a length and a destination that may not be reached by the edges
	private Node start, destination;
	private ArrayList<Edge> edges;
	private int length;
	
	/**
	 * creates new path
	 * @param start startnode
	 * @param e first edge
	 * @param destination destination node
	 */
	public Path(Node start, Edge e, Node destination){
		this.start = start;
		edges = new ArrayList<Edge>();
		edges.add(e);
		length = e.getWeight();
		this.destination = destination;
	}
	
	/**
	 * creates a NEW path from another path expanding it by one edge
	 * @param p old path
	 * @param last expansion edge
	 */
	public Path(Path p, Edge last){
		this.start = p.start;
		this.edges = new ArrayList<Edge>();
		for(Edge e : p.edges)
			this.edges.add(e);
		this.edges.add(last);
		this.length = p.length + last.getWeight();
		this.destination = p.destination;
	}
	
	/**
	 * adds an edge to the path
	 * @param e edge to be added
	 */
	public void add(Edge e){
		length += e.getWeight();
		edges.add(e);
	}
	
	public ArrayList<Edge> getEdges(){
		return edges;
	}
	
	/**
	 * gets the last node of the path
	 * @return last node
	 */
	public Node getLastNode(){
		return edges.get(edges.size()-1).getTarget();
	}
	
	/**
	 * compares two paths
	 * @param p path to compare with
	 * @return boolean if paths are "equal"
	 */
	public boolean equals(Path p) {
		return (start.equals(p.start) && edges.get(edges.size()-1).equals(p.edges.get(p.edges.size()-1)));
	}
	
	/**
	 * calculates the length of the actual path + the distance from the last node reached by edges to the destination
	 * @return actual length + heuristical length
	 */
	public double heuristicalLength(){
		return length + Math.sqrt( Math.pow(getLastNode().getX() - destination.getX(),2) + Math.pow(getLastNode().getY() - destination.getY(), 2));
	}

	@Override
	//compares lengths of two paths => priority queue
	public int compareTo(Path p) {
		if(this.heuristicalLength() < p.heuristicalLength()) 
			return -1;
		else if(this.heuristicalLength() == p.heuristicalLength())
			return 0;
		else
			return 1;
	}
	
	public int length(){
		return length;
	}

}
